home *** CD-ROM | disk | FTP | other *** search
/ Isometric Game Programming with DirectX 7.0 / Isometric Game Programming.iso / directx / dxf / samples / multimedia / directinput / mouse / mouse.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-04  |  25.9 KB  |  695 lines

  1. //-----------------------------------------------------------------------------
  2. // File: Mouse.cpp
  3. //
  4. // Desc: The Mouse sample show how to use a DirectInput mouse device and 
  5. //       the differences between cooperative levels and data styles. 
  6. //
  7. // Copyright (c) 1999-2000 Microsoft Corporation. All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #define STRICT
  10. #include <tchar.h>
  11. #include <windows.h>
  12. #include <basetsd.h>
  13. #include <dinput.h>
  14. #include <stdio.h>
  15. #include "resource.h"
  16.  
  17.  
  18.  
  19.  
  20. //-----------------------------------------------------------------------------
  21. // Function-prototypes
  22. //-----------------------------------------------------------------------------
  23. INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  24. HRESULT OnInitDialog( HWND hDlg );
  25. VOID    UpdateUI( HWND hDlg );
  26. HRESULT OnCreateDevice( HWND hDlg );
  27. HRESULT ReadImmediateData( HWND hDlg );
  28. HRESULT ReadBufferedData( HWND hDlg );
  29. VOID    FreeDirectInput();
  30.  
  31.  
  32.  
  33.  
  34. //-----------------------------------------------------------------------------
  35. // Defines, constants, and global variables
  36. //-----------------------------------------------------------------------------
  37. #define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }
  38. #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
  39.  
  40. #define SAMPLE_BUFFER_SIZE 16  // arbitrary number of buffer elements
  41.  
  42. LPDIRECTINPUT8       g_pDI    = NULL;         
  43. LPDIRECTINPUTDEVICE8 g_pMouse = NULL;     
  44.  
  45.  
  46.  
  47.  
  48. //-----------------------------------------------------------------------------
  49. // Name: WinMain()
  50. // Desc: Entry point for the application.  Since we use a simple dialog for 
  51. //       user interaction we don't need to pump messages.
  52. //-----------------------------------------------------------------------------
  53. int WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int )
  54. {
  55.     // Display the main dialog box.
  56.     DialogBox( hInst, MAKEINTRESOURCE(IDD_MOUSE), NULL, MainDlgProc );
  57.     
  58.     return TRUE;
  59. }
  60.  
  61.  
  62.  
  63.  
  64.  
  65. //-----------------------------------------------------------------------------
  66. // Name: MainDlgProc()
  67. // Desc: Handles dialog messages
  68. //-----------------------------------------------------------------------------
  69. INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  70. {
  71.     switch( msg ) 
  72.     {
  73.         case WM_INITDIALOG:
  74.             OnInitDialog( hDlg );
  75.             break;
  76.         
  77.         case WM_COMMAND:
  78.             switch( LOWORD(wParam) )
  79.             {
  80.                 case IDCANCEL:
  81.                     EndDialog( hDlg, 0 ); 
  82.                     break;
  83.  
  84.                 case IDC_EXCLUSIVE:
  85.                 case IDC_NONEXCLUSIVE:
  86.                 case IDC_FOREGROUND:
  87.                 case IDC_BACKGROUND:
  88.                 case IDC_IMMEDIATE:
  89.                 case IDC_BUFFERED:
  90.                     UpdateUI( hDlg );
  91.                     break;
  92.  
  93.                 case IDM_CREATEDEVICE:
  94.                 case IDM_RELEASEDEVICE:
  95.                 case IDC_CREATEDEVICE:
  96.                     if( NULL == g_pMouse )
  97.                     {                    
  98.                         if( FAILED( OnCreateDevice( hDlg ) ) )
  99.                         {
  100.                             MessageBox( hDlg, _T("CreateDevice() failed. ")
  101.                                               _T("The sample will now exit. "), 
  102.                                               _T("Mouse"), MB_ICONERROR | MB_OK );
  103.                             FreeDirectInput();
  104.                         }
  105.  
  106.                         SetFocus( GetDlgItem( hDlg, IDC_CREATEDEVICE ) );
  107.                     }
  108.                     else
  109.                     {
  110.                         FreeDirectInput();
  111.                     }
  112.  
  113.                     UpdateUI( hDlg );
  114.                     break;
  115.  
  116.                 default:
  117.                     return FALSE; // Message not handled 
  118.             }       
  119.             break;
  120.  
  121.         case WM_ENTERMENULOOP:
  122.             // Release the device, so if we are in exclusive mode the 
  123.             // cursor will reappear
  124.             if( g_pMouse )
  125.             {
  126.                 g_pMouse->Unacquire();
  127.                 KillTimer( hDlg, 0 );  // Stop timer, so device is not re-acquired
  128.                 SetDlgItemText( hDlg, IDC_DATA, "Unacquired" );
  129.             }
  130.             break;
  131.  
  132.         case WM_EXITMENULOOP:
  133.             // Make sure the device is acquired when coming out of a menu loop
  134.             if( g_pMouse )
  135.             {
  136.                 g_pMouse->Acquire();
  137.                 SetTimer( hDlg, 0, 1000 / 12, NULL ); // Start timer again
  138.             }
  139.             break;
  140.  
  141.         case WM_ACTIVATE:
  142.             if( WA_INACTIVE != wParam && g_pMouse )
  143.             {
  144.                 // Make sure the device is acquired, if we are gaining focus.
  145.                 g_pMouse->Acquire();
  146.             }
  147.             break;
  148.         
  149.         case WM_TIMER:
  150.             // Update the input device every timer message
  151.             {
  152.                 BOOL bImmediate = ( IsDlgButtonChecked( hDlg, IDC_IMMEDIATE  ) == BST_CHECKED );
  153.  
  154.                 if( bImmediate )
  155.                 {
  156.                     if( FAILED( ReadImmediateData( hDlg ) ) )
  157.                     {
  158.                         KillTimer( hDlg, 0 );    
  159.                         MessageBox( NULL, _T("Error Reading Input State. ")
  160.                                           _T("The sample will now exit. "), 
  161.                                           _T("Mouse"), MB_ICONERROR | MB_OK );
  162.                         EndDialog( hDlg, TRUE ); 
  163.                     }
  164.                 }
  165.                 else
  166.                 {
  167.                     if( FAILED( ReadBufferedData( hDlg ) ) )
  168.                     {
  169.                         KillTimer( hDlg, 0 );    
  170.                         MessageBox( NULL, _T("Error Reading Input State. ")
  171.                                           _T("The sample will now exit. "), 
  172.                                           _T("Mouse"), MB_ICONERROR | MB_OK );
  173.                         EndDialog( hDlg, TRUE ); 
  174.                     }
  175.                 }
  176.             }
  177.             break;
  178.         
  179.         case WM_DESTROY:
  180.             // Cleanup everything
  181.             KillTimer( hDlg, 0 );    
  182.             FreeDirectInput();    
  183.             break;
  184.  
  185.         default:
  186.             return FALSE; // Message not handled 
  187.     }
  188.  
  189.     return TRUE; // Message handled 
  190. }
  191.  
  192.  
  193.  
  194.  
  195. //-----------------------------------------------------------------------------
  196. // Name: OnInitDialog()
  197. // Desc: Initialize the DirectInput variables.
  198. //-----------------------------------------------------------------------------
  199. HRESULT OnInitDialog( HWND hDlg )
  200. {
  201.     // Load the icon
  202. #ifdef _WIN64
  203.     HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hDlg, GWLP_HINSTANCE );
  204. #else
  205.     HINSTANCE hInst = (HINSTANCE) GetWindowLong( hDlg, GWL_HINSTANCE );
  206. #endif
  207.     HICON hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN ) );
  208.  
  209.     // Set the icon for this dialog.
  210.     PostMessage( hDlg, WM_SETICON, ICON_BIG,   (LPARAM) hIcon );  // Set big icon
  211.     PostMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon );  // Set small icon
  212.  
  213.     // Check the 'exclusive', 'foreground', and 'immediate' buttons by default. 
  214.     CheckRadioButton( hDlg, IDC_EXCLUSIVE,  IDC_NONEXCLUSIVE, IDC_EXCLUSIVE );
  215.     CheckRadioButton( hDlg, IDC_FOREGROUND, IDC_BACKGROUND,   IDC_FOREGROUND );
  216.     CheckRadioButton( hDlg, IDC_IMMEDIATE,  IDC_BUFFERED,     IDC_IMMEDIATE );
  217.  
  218.     UpdateUI( hDlg );
  219.  
  220.     return S_OK;
  221. }
  222.  
  223.  
  224.  
  225.  
  226. //-----------------------------------------------------------------------------
  227. // Name: UpdateUI()
  228. // Desc: Enables/disables the UI, and sets the dialog behavior text based on the UI
  229. //-----------------------------------------------------------------------------
  230. VOID UpdateUI( HWND hDlg )
  231. {
  232.     TCHAR   strExcepted[2048];
  233.     BOOL    bExclusive;
  234.     BOOL    bForeground;
  235.     BOOL    bImmediate;
  236.  
  237.     // Detrimine where the buffer would like to be allocated 
  238.     bExclusive         = ( IsDlgButtonChecked( hDlg, IDC_EXCLUSIVE  ) == BST_CHECKED );
  239.     bForeground        = ( IsDlgButtonChecked( hDlg, IDC_FOREGROUND ) == BST_CHECKED );
  240.     bImmediate         = ( IsDlgButtonChecked( hDlg, IDC_IMMEDIATE  ) == BST_CHECKED );
  241.  
  242.     if( g_pMouse )
  243.     {
  244.         SetDlgItemText( hDlg, IDC_CREATEDEVICE, TEXT("&Release Device") );
  245.         EnableMenuItem( GetMenu( hDlg ), IDM_RELEASEDEVICE, MF_ENABLED );
  246.         EnableMenuItem( GetMenu( hDlg ), IDM_CREATEDEVICE,  MF_GRAYED );
  247.         SetDlgItemText( hDlg, IDC_DATA, TEXT("") );
  248.  
  249.         EnableWindow( GetDlgItem( hDlg, IDC_EXCLUSIVE    ), FALSE );
  250.         EnableWindow( GetDlgItem( hDlg, IDC_NONEXCLUSIVE ), FALSE );
  251.         EnableWindow( GetDlgItem( hDlg, IDC_FOREGROUND   ), FALSE );
  252.         EnableWindow( GetDlgItem( hDlg, IDC_BACKGROUND   ), FALSE );
  253.         EnableWindow( GetDlgItem( hDlg, IDC_IMMEDIATE    ), FALSE );
  254.         EnableWindow( GetDlgItem( hDlg, IDC_BUFFERED     ), FALSE );
  255.  
  256.         if( bExclusive )
  257.             SetDlgItemText( hDlg, IDC_HELP_TEXT, 
  258.                             TEXT("Press Enter to release the mouse device, "
  259.                             "and display the cursor again.") );
  260.     }
  261.     else
  262.     {
  263.         SetDlgItemText( hDlg, IDC_CREATEDEVICE, TEXT("&Create Device") );
  264.         EnableMenuItem( GetMenu( hDlg ), IDM_RELEASEDEVICE, MF_GRAYED );
  265.         EnableMenuItem( GetMenu( hDlg ), IDM_CREATEDEVICE,  MF_ENABLED );
  266.         SetDlgItemText( hDlg, IDC_DATA, TEXT("Device not created. Choose settings and click 'Create Device' then move mouse to see results") );   
  267.         SetDlgItemText( hDlg, IDC_HELP_TEXT, TEXT("") );
  268.  
  269.         EnableWindow( GetDlgItem( hDlg, IDC_EXCLUSIVE    ), TRUE );
  270.         EnableWindow( GetDlgItem( hDlg, IDC_NONEXCLUSIVE ), TRUE );
  271.         EnableWindow( GetDlgItem( hDlg, IDC_FOREGROUND   ), TRUE );
  272.         EnableWindow( GetDlgItem( hDlg, IDC_BACKGROUND   ), TRUE );
  273.         EnableWindow( GetDlgItem( hDlg, IDC_IMMEDIATE    ), TRUE );
  274.         EnableWindow( GetDlgItem( hDlg, IDC_BUFFERED     ), TRUE );
  275.     }
  276.  
  277.     // Figure what the user should expect based on the dialog choice
  278.     if( !bForeground && bExclusive )
  279.     {
  280.         strcpy( strExcepted, "For security reasons, background exclusive "
  281.                              "mouse access is not allowed.\n\n" );
  282.     }
  283.     else
  284.     {
  285.         if( bForeground )
  286.         {
  287.             strcpy( strExcepted, "Foreground cooperative level means that the "
  288.                                  "application has access to data only when in the "
  289.                                  "foreground or, in other words, has the input focus. "
  290.                                  "If the application moves to the background, "
  291.                                  "the device is automatically unacquired, or made "
  292.                                  "unavailable.\n\n" );
  293.         }
  294.         else
  295.         {
  296.             strcpy( strExcepted, "Background cooperative level really means "
  297.                                  "foreground and background. A device with a "
  298.                                  "background cooperative level can be acquired "
  299.                                  "and used by an application at any time.\n\n" );
  300.         }
  301.  
  302.         if( bExclusive )
  303.         {
  304.             strcat( strExcepted, "Exclusive mode prevents other applications from "
  305.                                  "also acquiring the device exclusively. The fact "
  306.                                  "that your application is using a device at the "
  307.                                  "exclusive level does not mean that other "
  308.                                  "applications cannot get data from the device. "
  309.                                  "Windows itself requires exclusive access to the "
  310.                                  "mouse because mouse events such as a click on "
  311.                                  "an inactive window could force an application "
  312.                                  "to unacquire the device, with potentially harmful "
  313.                                  "results, such as a loss of data from the input "
  314.                                  "buffer. Therefore, when an application has "
  315.                                  "exclusive access to the mouse, Windows is not "
  316.                                  "allowed any access at all. No mouse messages are "
  317.                                  "generated. A further side effect is that the "
  318.                                  "cursor disappears. When accessing the menu, the sample "
  319.                                  "releases the mouse so the mouse is displayed again.\n\n" );
  320.         }
  321.         else
  322.         {
  323.             strcat( strExcepted, "Nonexclusive mode means that other applications "
  324.                                  "can acquire device in exclusive or nonexclusive mode.\n\n" );
  325.         }
  326.  
  327.         if( bImmediate )
  328.         {
  329.             strcat( strExcepted, "Immediate data is a snapshot of the current "
  330.                                  "state of a device. It provides no data about "
  331.                                  "what has happened with the device since the "
  332.                                  "last call, apart from implicit information that "
  333.                                  "you can derive by comparing the current state with "
  334.                                  "the last one. Events in between calls are lost.\n\n" );
  335.         }
  336.         else
  337.         {
  338.             strcat( strExcepted, "Buffered data is a record of events that are stored "
  339.                                  "until an application retrieves them. With buffered "
  340.                                  "data, events are stored until you are ready to deal "
  341.                                  "with them. If the buffer overflows, new data is lost.\n\n" );                             
  342.         }
  343.  
  344.         strcat( strExcepted, "The sample will read the mouse 12 times a second. "
  345.                              "Typically an application would poll the mouse "
  346.                              "much faster than this, but this slow rate is simply "
  347.                              "for the purposes of demonstration." );
  348.     }
  349.  
  350.     // Tell the user what to expect
  351.     SetDlgItemText( hDlg, IDC_BEHAVIOR, strExcepted );
  352. }
  353.  
  354.  
  355.  
  356.  
  357. //-----------------------------------------------------------------------------
  358. // Name: OnCreateDevice()
  359. // Desc: Setups a the mouse device using the flags from the dialog.
  360. //-----------------------------------------------------------------------------
  361. HRESULT OnCreateDevice( HWND hDlg )
  362. {
  363.     HRESULT hr;
  364.     BOOL    bExclusive;
  365.     BOOL    bForeground;
  366.     BOOL    bImmediate;
  367.     DWORD   dwCoopFlags;
  368.  
  369.     // Cleanup any previous call first
  370.     KillTimer( hDlg, 0 );    
  371.     FreeDirectInput();
  372.  
  373.     // Detrimine where the buffer would like to be allocated 
  374.     bExclusive         = ( IsDlgButtonChecked( hDlg, IDC_EXCLUSIVE  ) == BST_CHECKED );
  375.     bForeground        = ( IsDlgButtonChecked( hDlg, IDC_FOREGROUND ) == BST_CHECKED );
  376.     bImmediate         = ( IsDlgButtonChecked( hDlg, IDC_IMMEDIATE  ) == BST_CHECKED );
  377.  
  378.     if( bExclusive )
  379.         dwCoopFlags = DISCL_EXCLUSIVE;
  380.     else
  381.         dwCoopFlags = DISCL_NONEXCLUSIVE;
  382.  
  383.     if( bForeground )
  384.         dwCoopFlags |= DISCL_FOREGROUND;
  385.     else
  386.         dwCoopFlags |= DISCL_BACKGROUND;
  387.  
  388.     // Create a DInput object
  389.     if( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, 
  390.                                          IID_IDirectInput8, (VOID**)&g_pDI, NULL ) ) )
  391.         return hr;
  392.     
  393.     // Obtain an interface to the system mouse device.
  394.     if( FAILED( hr = g_pDI->CreateDevice( GUID_SysMouse, &g_pMouse, NULL ) ) )
  395.         return hr;
  396.     
  397.     // Set the data format to "mouse format" - a predefined data format 
  398.     //
  399.     // A data format specifies which controls on a device we
  400.     // are interested in, and how they should be reported.
  401.     //
  402.     // This tells DirectInput that we will be passing a
  403.     // DIMOUSESTATE2 structure to IDirectInputDevice::GetDeviceState.
  404.     if( FAILED( hr = g_pMouse->SetDataFormat( &c_dfDIMouse2 ) ) )
  405.         return hr;
  406.     
  407.     // Set the cooperativity level to let DirectInput know how
  408.     // this device should interact with the system and with other
  409.     // DirectInput applications.
  410.     hr = g_pMouse->SetCooperativeLevel( hDlg, dwCoopFlags );
  411.     if( hr == DIERR_UNSUPPORTED && !bForeground && bExclusive )
  412.     {
  413.         FreeDirectInput();
  414.         MessageBox( hDlg, _T("SetCooperativeLevel() returned DIERR_UNSUPPORTED.\n")
  415.                           _T("For security reasons, background exclusive mouse\n")
  416.                           _T("access is not allowed."), 
  417.                           _T("Mouse"), MB_OK );
  418.         return S_OK;
  419.     }
  420.  
  421.     if( FAILED(hr) )
  422.         return hr;
  423.  
  424.     if( !bImmediate )
  425.     {
  426.         // IMPORTANT STEP TO USE BUFFERED DEVICE DATA!
  427.         //
  428.         // DirectInput uses unbuffered I/O (buffer size = 0) by default.
  429.         // If you want to read buffered data, you need to set a nonzero
  430.         // buffer size.
  431.         //
  432.         // Set the buffer size to SAMPLE_BUFFER_SIZE (defined above) elements.
  433.         //
  434.         // The buffer size is a DWORD property associated with the device.
  435.         DIPROPDWORD dipdw;
  436.         dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
  437.         dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  438.         dipdw.diph.dwObj        = 0;
  439.         dipdw.diph.dwHow        = DIPH_DEVICE;
  440.         dipdw.dwData            = SAMPLE_BUFFER_SIZE; // Arbitary buffer size
  441.  
  442.         if( FAILED( hr = g_pMouse->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ) ) )
  443.             return hr;
  444.     }
  445.  
  446.     // Acquire the newly created device
  447.     g_pMouse->Acquire();
  448.  
  449.     // Set a timer to go off 12 times a second, to read input
  450.     // Note: Typically an application would poll the mouse
  451.     //       much faster than this, but this slow rate is simply 
  452.     //       for the purposes of demonstration
  453.     SetTimer( hDlg, 0, 1000 / 12, NULL );
  454.  
  455.     return S_OK;
  456. }
  457.  
  458.  
  459.  
  460.  
  461. //-----------------------------------------------------------------------------
  462. // Name: ReadImmediateData()
  463. // Desc: Read the input device's state when in immediate mode and display it.
  464. //-----------------------------------------------------------------------------
  465. HRESULT ReadImmediateData( HWND hDlg )
  466. {
  467.     HRESULT       hr;
  468.     TCHAR         strNewText[256] = TEXT("");
  469.     DIMOUSESTATE2 dims2;      // DirectInput mouse state structure
  470.  
  471.     if( NULL == g_pMouse ) 
  472.         return S_OK;
  473.     
  474.     // Get the input's device state, and put the state in dims
  475.     ZeroMemory( &dims2, sizeof(dims2) );
  476.     hr = g_pMouse->GetDeviceState( sizeof(DIMOUSESTATE2), &dims2 );
  477.     if( FAILED(hr) ) 
  478.     {
  479.         // DirectInput may be telling us that the input stream has been
  480.         // interrupted.  We aren't tracking any state between polls, so
  481.         // we don't have any special reset that needs to be done.
  482.         // We just re-acquire and try again.
  483.         
  484.         // If input is lost then acquire and keep trying 
  485.         hr = g_pMouse->Acquire();
  486.         while( hr == DIERR_INPUTLOST ) 
  487.             hr = g_pMouse->Acquire();
  488.  
  489.         // Update the dialog text 
  490.         if( hr == DIERR_OTHERAPPHASPRIO || 
  491.             hr == DIERR_NOTACQUIRED ) 
  492.             SetDlgItemText( hDlg, IDC_DATA, "Unacquired" );
  493.  
  494.         // hr may be DIERR_OTHERAPPHASPRIO or other errors.  This
  495.         // may occur when the app is minimized or in the process of 
  496.         // switching, so just try again later 
  497.         return S_OK; 
  498.     }
  499.     
  500.     // The dims structure now has the state of the mouse, so 
  501.     // display mouse coordinates (x, y, z) and buttons.
  502.     sprintf( strNewText, "(X=% 3.3d, Y=% 3.3d, Z=% 3.3d) B0=%c B1=%c B2=%c B3=%c B4=%c B5=%c B6=%c B7=%c",
  503.                          dims2.lX, dims2.lY, dims2.lZ,
  504.                         (dims2.rgbButtons[0] & 0x80) ? '1' : '0',
  505.                         (dims2.rgbButtons[1] & 0x80) ? '1' : '0',
  506.                         (dims2.rgbButtons[2] & 0x80) ? '1' : '0',
  507.                         (dims2.rgbButtons[3] & 0x80) ? '1' : '0',
  508.                         (dims2.rgbButtons[4] & 0x80) ? '1' : '0',
  509.                         (dims2.rgbButtons[5] & 0x80) ? '1' : '0',
  510.                         (dims2.rgbButtons[6] & 0x80) ? '1' : '0',
  511.                         (dims2.rgbButtons[7] & 0x80) ? '1' : '0');
  512.  
  513.     // Get the old text in the text box
  514.     TCHAR strOldText[128];
  515.     GetDlgItemText( hDlg, IDC_DATA, strOldText, 127 );
  516.     
  517.     // If nothing changed then don't repaint - avoid flicker
  518.     if( 0 != lstrcmp( strOldText, strNewText ) ) 
  519.         SetDlgItemText( hDlg, IDC_DATA, strNewText );
  520.     
  521.     return S_OK;
  522. }
  523.  
  524.  
  525.  
  526.  
  527. //-----------------------------------------------------------------------------
  528. // Name: ReadBufferedData()
  529. // Desc: Read the input device's state when in buffered mode and display it.
  530. //-----------------------------------------------------------------------------
  531. HRESULT ReadBufferedData( HWND hDlg )
  532. {
  533.     TCHAR              strNewText[256*5 + 1] = TEXT("");
  534.     TCHAR              strElement[10];    
  535.     DIDEVICEOBJECTDATA didod[ SAMPLE_BUFFER_SIZE ];  // Receives buffered data 
  536.     DWORD              dwElements;
  537.     DWORD              i;
  538.     HRESULT            hr;
  539.  
  540.     if( NULL == g_pMouse ) 
  541.         return S_OK;
  542.     
  543.     dwElements = SAMPLE_BUFFER_SIZE;
  544.     hr = g_pMouse->GetDeviceData( sizeof(DIDEVICEOBJECTDATA),
  545.                                      didod, &dwElements, 0 );
  546.     if( hr != DI_OK ) 
  547.     {
  548.         // We got an error or we got DI_BUFFEROVERFLOW.
  549.         //
  550.         // Either way, it means that continuous contact with the
  551.         // device has been lost, either due to an external
  552.         // interruption, or because the buffer overflowed
  553.         // and some events were lost.
  554.         //
  555.         // Consequently, if a button was pressed at the time
  556.         // the buffer overflowed or the connection was broken,
  557.         // the corresponding "up" message might have been lost.
  558.         //
  559.         // But since our simple sample doesn't actually have
  560.         // any state associated with button up or down events,
  561.         // there is no state to reset.  (In a real game, ignoring
  562.         // the buffer overflow would result in the game thinking
  563.         // a key was held down when in fact it isn't; it's just
  564.         // that the "up" event got lost because the buffer
  565.         // overflowed.)
  566.         //
  567.         // If we want to be cleverer, we could do a
  568.         // GetDeviceState() and compare the current state
  569.         // against the state we think the device is in,
  570.         // and process all the states that are currently
  571.         // different from our private state.
  572.         hr = g_pMouse->Acquire();
  573.         while( hr == DIERR_INPUTLOST ) 
  574.             hr = g_pMouse->Acquire();
  575.  
  576.         // Update the dialog text 
  577.         if( hr == DIERR_OTHERAPPHASPRIO || 
  578.             hr == DIERR_NOTACQUIRED ) 
  579.             SetDlgItemText( hDlg, IDC_DATA, "Unacquired" );
  580.  
  581.         // hr may be DIERR_OTHERAPPHASPRIO or other errors.  This
  582.         // may occur when the app is minimized or in the process of 
  583.         // switching, so just try again later 
  584.         return S_OK; 
  585.     }
  586.  
  587.     if( FAILED(hr) )  
  588.         return hr;
  589.  
  590.     // Study each of the buffer elements and process them.
  591.     //
  592.     // Since we really don't do anything, our "processing"
  593.     // consists merely of squirting the name into our
  594.     // local buffer.
  595.     for( i = 0; i < dwElements; i++ ) 
  596.     {
  597.         // this will display then scan code of the key
  598.         // plus a 'D' - meaning the key was pressed 
  599.         //   or a 'U' - meaning the key was released
  600.         switch( didod[ i ].dwOfs )
  601.         {
  602.             case DIMOFS_BUTTON0:
  603.                 strcpy( strElement, "B0" );
  604.                 break;
  605.  
  606.             case DIMOFS_BUTTON1:
  607.                 strcpy( strElement, "B1" );
  608.                 break;
  609.  
  610.             case DIMOFS_BUTTON2:
  611.                 strcpy( strElement, "B2" );
  612.                 break;
  613.  
  614.             case DIMOFS_BUTTON3:
  615.                 strcpy( strElement, "B3" );
  616.                 break;
  617.  
  618.             case DIMOFS_X:
  619.                 strcpy( strElement, "X" );
  620.                 break;
  621.  
  622.             case DIMOFS_Y:
  623.                 strcpy( strElement, "Y" );
  624.                 break;
  625.  
  626.             case DIMOFS_Z:
  627.                 strcpy( strElement, "Z" );
  628.                 break;
  629.  
  630.             default:
  631.                 strcpy( strElement, "" );
  632.         }
  633.  
  634.         switch( didod[ i ].dwOfs )
  635.         {
  636.             case DIMOFS_BUTTON0:
  637.             case DIMOFS_BUTTON1:
  638.             case DIMOFS_BUTTON2:
  639.             case DIMOFS_BUTTON3:
  640.                 if( didod[ i ].dwData & 0x80 )
  641.                     strcat( strElement, "U " );
  642.                 else
  643.                     strcat( strElement, "D " );
  644.                 break;
  645.  
  646.             case DIMOFS_X:
  647.             case DIMOFS_Y:
  648.             case DIMOFS_Z:
  649.             {
  650.                 TCHAR strCoordValue[255];
  651.                 wsprintf( strCoordValue, "%d ", didod[ i ].dwData );
  652.                 strcat( strElement, strCoordValue );
  653.                 break;
  654.             }
  655.         }
  656.  
  657.         strcat( strNewText, strElement );
  658.     }
  659.  
  660.     // Get the old text in the text box
  661.     TCHAR strOldText[128];
  662.     GetDlgItemText( hDlg, IDC_DATA, strOldText, 127 );
  663.  
  664.     // If nothing changed then don't repaint - avoid flicker
  665.     if( 0 != lstrcmp( strOldText, strNewText ) ) 
  666.         SetDlgItemText( hDlg, IDC_DATA, strNewText );    
  667.  
  668.     return S_OK;
  669. }
  670.  
  671.  
  672.  
  673.  
  674. //-----------------------------------------------------------------------------
  675. // Name: FreeDirectInput()
  676. // Desc: Initialize the DirectInput variables.
  677. //-----------------------------------------------------------------------------
  678. VOID FreeDirectInput()
  679. {
  680.     // Unacquire the device one last time just in case 
  681.     // the app tried to exit while the device is still acquired.
  682.     if( g_pMouse ) 
  683.         g_pMouse->Unacquire();
  684.     
  685.     // Release any DirectInput objects.
  686.     SAFE_RELEASE( g_pMouse );
  687.     SAFE_RELEASE( g_pDI );
  688. }
  689.  
  690.  
  691.  
  692.  
  693.  
  694.  
  695.